package edu.hawaii.duedates.libraries;

import java.io.IOException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;

import org.xml.sax.SAXException;

import com.meterware.httpunit.GetMethodWebRequest;
import com.meterware.httpunit.HttpUnitOptions;
import com.meterware.httpunit.WebConversation;
import com.meterware.httpunit.WebForm;
import com.meterware.httpunit.WebLink;
import com.meterware.httpunit.WebRequest;
import com.meterware.httpunit.WebResponse;
import com.meterware.httpunit.WebTable;

import edu.hawaii.duedates.BorrowedItem;
import edu.hawaii.duedates.LenderQuery;

/**
 * Hawaii State Public Library class. Contains all the necessary methods to log
 * in and retrieve the borrowed items from the library system.
 * 
 * @author Daniel Tian, Aric West
 */
public class HawaiiStatePublicLibraryQuery extends LenderQuery {
  WebConversation conversation;
  private final String url;

  /**
   * Constructor. Assigns the number of fields this class expects, the full
   * library name, and instantiates the ArrayList object used to store the list
   * of borrowed items.
   */
  public HawaiiStatePublicLibraryQuery() {
    this.expectedNumberOfFields = 2;
    this.lenderName = "Hawaii State Public Library System";
    this.itemList = new ArrayList<BorrowedItem>();
    this.conversation = new WebConversation();
    this.url = "http://www.librarieshawaii.org/";
  }

  /**
   * Acquires and generates the list of borrowed items and their duedates.
   * 
   * @return A list of borrowed items.
   */
  @Override
  public boolean parseBorrowedItems() {
    try {
      WebResponse response = this.conversation.getCurrentPage();
      WebLink link = response.getLinkWith("Items Out");
      link.click();
      response = conversation.getCurrentPage();
      if (!response.getText().contains("Checked Out: 0")) {
        WebTable table = response.getTableStartingWith("Title");
        List<String> fieldList = new ArrayList<String>();

        for (int i = 1; i < table.getRowCount(); i++) {
          fieldList.add(table.getCellAsText(i, 0).replaceAll("\n", ""));
          fieldList.add(table.getCellAsText(i, 2));
          fieldList.add(this.lenderName);
          BorrowedItem item = new BorrowedItem(fieldList);
          this.itemList.add(item);
          fieldList.clear();
        }
        return true;
      }

    } 
    catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } 
    catch (SAXException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    catch (ParseException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    return false;
  }

  /**
   * Logs into the Hawaii State Public Library system using a library id and a
   * PIN. This code is modified from Philip Johnson's bootstrap code available
   * here:
   * 
   * http://groups.google.com/group/ics-software-engineering-fall-2008/
   * web/DueDateBootstrap-1.0.1010.zip
   * 
   * @param fieldList List of log in credentials. 
   * @return A WebConversation instance after successful login.
   */
  @Override
  public boolean logIn(List<String> fieldList) {
    if (fieldList.size() == this.expectedNumberOfFields) {
      try {
        // Website has bogus JavaScript code.
        HttpUnitOptions.setExceptionsThrownOnScriptError(false);

        WebRequest request = new GetMethodWebRequest(this.url);
        WebResponse response = this.conversation.getResponse(request);
        WebLink link = response.getLinkWith("My Account");
        link.click();
        response = conversation.getCurrentPage();
        WebForm form = response.getForms()[0];
        form.setParameter("sec1", fieldList.get(0));
        form.setParameter("sec2", fieldList.get(1));
        form.submit();
      }
      catch (Exception e) {
        e.printStackTrace();
      }
    }
    return true;
  }
  
  /**
   * Checks that a compared object is this type they have the same name and item list.
   * Also should later check for equality of id and last name.
   * 
   * @param o object
   * @return boolean value
   */
  public boolean equals(Object o) {
    return o != null 
        && this.getClass().equals(o.getClass())
        && this.lenderName.equals( ((HawaiiStatePublicLibraryQuery) o).getLenderName() )
        && this.itemList.equals( ((HawaiiStatePublicLibraryQuery) o).getItemList() );
  }

  /**
   * Calculates a hashcode for this object based on size of book list and expected parameters size.
   * Should use the id number later.
   * 
   * @return A hash value based on the due date of the item.
   */
  public int hashCode() {
    int hash = 7;
    int listSize = Integer.valueOf(this.itemList.size());
    hash = hash + ((listSize + this.expectedNumberOfFields) * 31);
    return hash;
  }
}